<?php
/* 
 * Sopily is simple and fastest php template engine
 * it modified from smarty http://www.smarty.net/
 *
 * Project: Sopily
 * Version: 2009.05.13
 * License: LGPL v2.1
 * Link: http://code.google.com/p/sopily/
 * Author: Girvan Liu (Li-Jen) girvanliu@gmail.com
 * Author's website: http://www.sopili.net/
 * */


class Sopily{

	var $config_dir='configs';
	var $template_dir='templates';
	var $cache_dir='cache';

	var $caching=0;	// 0 for no cacheing, 1 for caching
	var $cache_lifetime  =  3600;

	var $func_prefix='_';	// name prefix of modifiers and functions
	var $use_function=true;	// load modifier and functions, if false, it will be faster


	var $_functions=Array();	//modifiers and functions 

	var $_tpl_vars;	//assigned variable

	var $_sep;	//sepecrator
	var $_dir;	//directory for this file
	var $_plugin_dir;


	var $_original_include_path;


	function Sopily(){
		$this->_sep=DIRECTORY_SEPARATOR;
		$this->_dir=dirname(__FILE__);

		$this->_plugin_dir=$this->_dir.$this->_sep.'Sopily-plugins'.$this->_sep;

		//load plugin
		if($this->use_function && is_file($this->_plugin_dir.'functions.php'))
			require_once($this->_plugin_dir.'functions.php');
	}

	//copy from smarty
	/**
	 * assigns values to template variables
	 *
	 * @param array|string $tpl_var the template variable name(s)
	 * @param mixed $value the value to assign
	 */
	function assign($tpl_var, $value = null)
	{
		if (is_array($tpl_var)){
			foreach ($tpl_var as $key => $val) {
				if ($key != '') {
					$this->_tpl_vars[$key] = $val;
				}
			}
		} else {
			if ($tpl_var != '')
				$this->_tpl_vars[$tpl_var] = $value;
		}
	}

	//copy from smarty
	/**
    	 * assigns values to template variables by reference
    	 *
    	 * @param string $tpl_var the template variable name
    	 * @param mixed $value the referenced value to assign
    	 */
	function assign_by_ref($tpl_var, &$value)
	{
		if ($tpl_var != '')
			$this->_tpl_vars[$tpl_var] = &$value;
	}

	//copy from smarty
	/**
    	 * clear the given assigned template variable.
    	 *
    	 * @param string $tpl_var the template variable to clear
    	 */
	function clear_assign($tpl_var)
	{
		if (is_array($tpl_var))
			foreach ($tpl_var as $curr_var)
				unset($this->_tpl_vars[$curr_var]);
		else
			unset($this->_tpl_vars[$tpl_var]);
	}

	//copy from smarty
	/**
	 * clear all the assigned template variables.
	 *
	 */
	function clear_all_assign()
	{
		$this->_tpl_vars = array();
	}

	//copy from smarty
	/**
	 * appends values to template variables
	 *
	 * @param array|string $tpl_var the template variable name(s)
	 * @param mixed $value the value to append
	 */
	function append($tpl_var, $value=null, $merge=false)
	{
		if (is_array($tpl_var)) {
			// $tpl_var is an array, ignore $value
			foreach ($tpl_var as $_key => $_val) {
				if ($_key != '') {
					if(!@is_array($this->_tpl_vars[$_key])) {
						settype($this->_tpl_vars[$_key],'array');
					}
					if($merge && is_array($_val)) {
						foreach($_val as $_mkey => $_mval) {
							$this->_tpl_vars[$_key][$_mkey] = $_mval;
						}
		    			} else {
						$this->_tpl_vars[$_key][] = $_val;
		    			}
				}
	    		}
		} else {
	    		if ($tpl_var != '' && isset($value)) {
				if(!@is_array($this->_tpl_vars[$tpl_var])) {
		    			settype($this->_tpl_vars[$tpl_var],'array');
				}
				if($merge && is_array($value)) {
		    			foreach($value as $_mkey => $_mval) {
						$this->_tpl_vars[$tpl_var][$_mkey] = $_mval;
		    			}
				} else {
		    			$this->_tpl_vars[$tpl_var][] = $value;
				}
	    		}
		}
    	}

	//copy from smarty
    	/**
    	 * appends values to template variables by reference
    	 *
    	 * @param string $tpl_var the template variable name
    	 * @param mixed $value the referenced value to append
    	 */
    	function append_by_ref($tpl_var, &$value, $merge=false)
    	{
		if ($tpl_var != '' && isset($value)) {
	    		if(!@is_array($this->_tpl_vars[$tpl_var])) {
		   		settype($this->_tpl_vars[$tpl_var],'array');
	    		}
	    		if ($merge && is_array($value)) {
				foreach($value as $_key => $_val) {
		    			$this->_tpl_vars[$tpl_var][$_key] = &$value[$_key];
				}
	    		} else {
				$this->_tpl_vars[$tpl_var][] = &$value;
	    		}
		}
    	}


	/**
	 * clear cached content for the given template and cache id
	 *
	 * @param string $tpl_file name of template file
	 * @param string $cache_id name of cache_id
	 * @param string $compile_id name of compile_id
	 * @param string $exp_time expiration time
	 */
	function clear_cache($tpl_file = null, $cache_id = null, $exp_time = null)
	{

		$cache_file=$this->_get_auto_filename($this->cache_dir,$tpl_file,$cache_id);
		$base_cache_file=substr($this->_get_auto_filename('',$tpl_file,null),1);

		$handle=opendir($this->cache_dir);
		while (false !== ($file = readdir($handle))) {
			if(in_array($file,Array('','.','..')))
				continue;

			if(empty($cache_id) && !empty($tpl_file)){
				$pattern="/^[\w\^]*".preg_quote($base_cache_file,'/')."$/";
				if(!preg_match($pattern,$file))
					continue;
			}else if(!empty($cache_id) && !empty($tpl_file)){
				$pattern="/^". preg_quote( str_replace('|','^',$cache_id) , '/' )."\^[\w\^]*".preg_quote($base_cache_file,'/')."$/";
				if(!preg_match($pattern,$file))
					continue;
			}else if(!empty($cache_id) && empty($tpl_file)){
				$pattern="/^". preg_quote( str_replace('|','^',$cache_id) , '/' )."\^.*$/";
				if(!preg_match($pattern,$file))
					continue;
			}
			/*
			else if(empty($cache_id) && empty($tpl_file)){

			}
			 */

			//only check if exp_time set
			if( intval($exp_time)>0 && filemtime($this->cache_dir.$this->_sep.$file)+$exp_time>time())
				continue;

			@unlink($this->cache_dir.$this->_sep.$file);
		}
		closedir($handle);

	}

      	function clear_all_cache($exp_time = null)
    	{
		return $this->clear_cache(null, null, null, $exp_time);
    	}



	function display($resource_name, $cache_id = null){
		$this->fetch($resource_name, $cache_id,true);
	}
	function fetch($resource_name, $cache_id = null, $display = false){


		if($this->caching && $this->is_cached($resource_name,$cache_id)){
			$cache_file=$this->_get_auto_filename($this->cache_dir,$resource_name,$cache_id);
			if($display){
				echo file_get_contents($cache_file);
				return;
			}
			else
				return file_get_contents($cache_file);
		}

		global $sopily_instance;
		$sopily_instance=$this;

		$this->_include_convert();

		$this->_create_function();

		if(!empty($this->_functions)){
			reset($this->_functions);
			do{
				$func=key($this->_functions);
				${$this->func_prefix.$func}=&$this->_functions[$func];
			}
			while(next($this->_functions));
		}


		global $sopily_config;
		$sopily_config=Array();

		//process variable
    if(is_array($this->_tpl_vars))
        extract($this->_tpl_vars);

		if(!$display || $this->caching>0)
			ob_start();

		require($this->template_dir.$this->_sep.$resource_name);

		if(!$display || $this->caching>0){
			$html = ob_get_contents();
			ob_end_clean();

			if($this->caching>0){
				$cache_file=$this->_get_auto_filename($this->cache_dir,$resource_name,$cache_id);
				//save into cache
				$handle=fopen($cache_file,'w+');
				fwrite($handle,$html);
				fclose($handle);
			}

			if($display){
				echo $html;
			}


		}

		$this->_include_restore();
		if(!$display)
			return $html;
		//		var_dump($this->_tpl_vars);
	}

	//copy from smarty
	function is_cached($tpl_file, $cache_id = null)
	{
		if (!$this->caching)
			return false;

		$cache_file=$this->_get_auto_filename($this->cache_dir,$tpl_file,$cache_id);
		if(is_file($cache_file) && filemtime($cache_file)+$this->cache_lifetime>time())
			return true;
		return false;
    	}

	//copy from smarty
	function _get_auto_filename($auto_base, $auto_source = null, $auto_id = null)
	{
		$_compile_dir_sep =  $this->use_sub_dirs ? DIRECTORY_SEPARATOR : '^';
		$_return = $auto_base . DIRECTORY_SEPARATOR;

		if(isset($auto_id)) {
	    		// make auto_id safe for directory names
	    		$auto_id = str_replace('%7C',$_compile_dir_sep,(urlencode($auto_id)));
	    		// split into separate directories
	    		$_return .= $auto_id . $_compile_dir_sep;
		}

		if(isset($auto_source)) {
	    		// make source name safe for filename
	    		$_filename = urlencode(basename($auto_source));
	    		$_crc32 = sprintf('%08X', crc32($auto_source));
	    		// prepend %% to avoid name conflicts with
	    		// with $params['auto_id'] names
	    		$_crc32 = substr($_crc32, 0, 2) . $_compile_dir_sep .
	  			substr($_crc32, 0, 3) . $_compile_dir_sep . $_crc32;
	    		$_return .= '%%' . $_crc32 . '%%' . $_filename;
		}

		$_return.='.txt';	//for security

		return $_return;
    	}


	function _create_function(){
		if(empty($this->_functions) && function_exists('sopily_create_function'))
			sopily_create_function($this);
	}

	//_get_plugin_filepath('shared', 'make_timestamp');
	//shared.make_timestamp.php
	function _get_plugin_filepath($type,$name){
		return $this->_plugin_dir.$type.'.'.$name.'.php';
	}

	function _include_convert(){
		$this->_original_include_path=ini_get('include_path');

		ini_set('include_path',$this->template_dir);
	}
	function _include_restore(){
		ini_set('include_path',$this->_original_include_path);
	}

}

?>
